use rbatis::rbdc::Error;
use crate::core::CTX;
use crate::domain::dto::login_dto::{UserLoginRequest, UserLoginResponse};
use crate::domain::dto::PageRes;
use crate::domain::dto::user_dto::UserCreateRequest;
use crate::domain::entity::user_entity::UserEntity;
use crate::domain::error::{AccountError, AppResult};
use crate::domain::{PASSWORD_SALT, REDIS_ACCESS_TOKEN_KEY_KEY, REDIS_REFRESH_TOKEN_KEY_KEY};
use crate::mapper::user_mapper;
use crate::service::redis_service;
use crate::utils;
use crate::utils::tool::{build_sh265, create_access_token, create_refresh_token};

pub async fn create_user(param: UserCreateRequest) -> rbatis::Result<bool> {
    // 判断用户名是否存在
    let has_user = UserEntity::select_by_column(&mut CTX.db.clone(), "username", &param.username).await?;
    if has_user.len() >0 {
        return Err(Error::from(AccountError::CreateUserError.to_string()))
    }
    // 密码加密
    let password = format!("{:x}", md5::compute(param.password.clone()));
    let mut user: UserEntity = param.into();
    user.password = password;
    let result = UserEntity::insert(&mut CTX.db.clone(), &user).await?;
    Ok(result.rows_affected == 1)
}

/// user_page 用户分页查询
/// @param
pub async fn user_page(start: u64, length: u64, user_type: Option<u8>, username: Option<String>) -> rbatis::Result<PageRes<UserEntity>> {
    let (num,size) = utils::tool::page_tools(start, length);
    let list = user_mapper::select_user_page(&mut CTX.db.clone(), num, size, username.clone(), user_type.clone()).await?;
    let total = user_mapper::select_user_page_count(&mut CTX.db.clone(), username.clone(), user_type.clone()).await?;
    Ok(PageRes {
        page: start,
        limit: length,
        total,
        row: list,
    })
}

/// user_delete 删除用户
pub async fn user_delete(id: u64) -> rbatis::Result<String> {
    // 用户是否存在

    // 是否是登录的用户

    // 删除用户

    todo!()
}

/// user_login 用户登录
pub async fn user_login(param: UserLoginRequest) -> AppResult<UserLoginResponse> {
    let captcha = redis_service::get(param.code_key.clone()).map_or(String::new(), |v| v );
    tracing::info!("user_login captcha: {} : {}", captcha, param.code_key);
    if captcha.is_empty() || !captcha.eq(&param.code.to_lowercase()) {
        return Err(AccountError::CaptchaNotMatchError)
    }
    // 移除缓冲
    redis_service::del(param.code.clone()).unwrap();
    let user = match user_mapper::select_by_name(&mut CTX.db.clone(), &param.username).await {
        Ok(Some(user)) => user,
        Ok(None) => return Err(AccountError::UserNotExistError),
        Err(err) => {
            tracing::error!("查询用户数据异常: {:#?}", err);
            return Err(AccountError::OperationError)
        }
    };
    tracing::info!("用户信息: {:?}", user);

    // 验证密码
    let pw = build_sh265(param.password.as_str(), PASSWORD_SALT);
    tracing::info!("生成的密码: {}", pw);
    if !user.password.eq(pw.as_str()) {
        return Err(AccountError::UserPasswdNotExistError)
    }

    //  认证 token 过期时间 10分钟
    let access_token = match create_access_token(user.clone(), 10) {
        Ok(t) => t,
        Err(err) => {
            tracing::error!("创建 Access Token 异常: {:#?}", err);
            return Err(AccountError::SystemError)
        }
    };
    tracing::info!("构建access_token: {}", access_token);

    // 刷新 token 过期时间 7天
    let refresh_token = match create_refresh_token(user.id, 60 * 24 *  7) {
        Ok(t) => t,
        Err(err) => {
            tracing::error!("创建 Refresh Token 异常: {:#?}", err);
            return Err(AccountError::SystemError)
        }
    };
    tracing::info!("构建refresh_token: {}", refresh_token);


    let build_key = |prefix: &str, token: &str| format!("{}:{}", prefix, token);
    let access_key = build_key(REDIS_ACCESS_TOKEN_KEY_KEY, &access_token);
    // 存入Redis
    redis_service::set_ex(build_key(REDIS_ACCESS_TOKEN_KEY_KEY, &access_token), user.clone(),10 * 60).unwrap();
    redis_service::set_ex(build_key(REDIS_REFRESH_TOKEN_KEY_KEY, &refresh_token), access_key.clone(),60 * 60 * 24 * 7).unwrap();
    Ok(UserLoginResponse::new(access_token, refresh_token, user))
}